(function(layui, window, document) {
  'use strict';

  layui = layui && layui.hasOwnProperty('default') ? layui['default'] : layui;

  // 使用的类名
  var ClassName = {
    MENU          : 'layui-menu',
    IS_SUBMENU    : 'is-submenu',
    IS_SHRINK     : 'is-shrink',
    ITEM          : 'layui-menu-item',
    ITEMICON      : 'layui-menu-item-icon',
    ITEMLABEL     : 'layui-menu-item-label',
    ITEMINNER     : 'layui-menu-item-inner',
    ITEMARROW     : 'layui-menu-item-arrow',
    ITEM_IS_ACTIVE: 'is-active',
    ITEM_IS_HOVER : 'is-hover',
    ITEM_IS_OPENED: 'is-opened',
    ITEM_HAS_MENU : 'has-menu',
    BADGE         : 'layui-menu-badge'
  };

  var MODULE_NAME = 'NavMenu'; // 导出的模块名

  layui.define(['jquery', 'layer'], function(exports) {
    var $ = layui.jquery;
    var layer = layui.layer;

    var renderHandler = function(data, getIcon) {
      var that = this;

      var iterator = function iterator(data) {
        var isRoot = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
        var tips = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
        var html = '<ul class="'.concat(ClassName.MENU).concat(isRoot ? '' : ' ' + ClassName.IS_SUBMENU, '" role="menu">');
        $.each(data, function(_, t) {
          var id = t[that.config.keyId];
          var children = t[that.config.keyChildren];
          var label = t[that.config.keyLabel];
          var path = t[that.config.keyPath];
          var count = $.type(t[that.config.keyCount]) === 'boolean' ? 0 : +t[that.config.keyCount];
          var icon = $.trim($.type(getIcon) === 'function' ? getIcon(t) : t[that.config.keyIcon]);
          var hasChildren = $.isArray(children) && children.length > 0;
          var itemClass = [ClassName.ITEM];

          if (hasChildren) {
            itemClass.push(ClassName.ITEM_HAS_MENU);
          }

          if (that.config.selected === id) {
            itemClass.push(hasChildren ? ClassName.ITEM_IS_OPENED : ClassName.ITEM_IS_ACTIVE); // 包含子导航则展开
          }

          var newTips = tips.slice(0);
          newTips.push(label);
          var itemContent = ['<div class="'.concat(ClassName.ITEMINNER, '">'), icon ? '<i class="'.concat(ClassName.ITEMICON, ' ').concat(icon, '"></i>') : '', '<span class="'.concat(ClassName.ITEMLABEL, '">').concat(label, '</span>'), count > 0 ? '<span class="'.concat(ClassName.BADGE, '">').concat(count > that.config.maxCount ? ''.concat(that.config.maxCount, '+') : count, '</span>') : '', hasChildren ? '<i class="'.concat(ClassName.ITEMARROW, ' layui-icon layui-icon-right"></i>') : '', '</div>', hasChildren ? iterator(children, false, newTips) : '']; // 如果当前导航包含子导航，作用其本身的链接失效

          html += '<li class="'.concat($.trim(itemClass.join(' ')), '" role="menuitem" data-id="').concat(id, '" data-label="').concat(label, '" data-level="').concat(newTips.length, '" data-tips="').concat(newTips.join('/'), '"').concat(!hasChildren && path ? ' lay-href="'.concat(path, '"') : '', '>').concat(itemContent.join(''), '</li>');
        });
        html += '</ul>';
        return html;
      };

      return $.isArray(data) ? iterator(data) : '';
    };

    var NavMenu = function(options) {
      this.config = $.extend({
        selected   : null,
        maxCount   : 99,
        keyId      : 'id', // 唯一化标识
        keyChildren: 'children',
        keySpread  : 'spread',
        keyLabel   : 'label',
        keyIcon    : 'icon',
        keyPath    : 'path',
        keyCount   : 'count'
      }, options);
      this.$elem = null;
      this.data = [];
    };

    NavMenu.prototype.$on = function(eventType, callback) {
      return layui.onevent.call(this, MODULE_NAME, eventType, callback);
    };

    NavMenu.prototype.$emit = function(eventType, params) {
      layui.event.call(this, MODULE_NAME, eventType, params);
    };

    NavMenu.prototype.render = function(elem, data, getIcon) {
      this.$elem = $(elem);
      if (!this.$elem.length) return;

      this.data = data;
      this.$elem.html(renderHandler.call(this, data, getIcon));
      this.bindEvents();
    };

    NavMenu.prototype.select = function(target) {
      if (!this.$elem || !this.$elem.length) return;

      var $old = this.$elem.find('.'.concat(ClassName.ITEM_IS_ACTIVE));
      var $target = $('[data-id="'.concat(target, '"]'));

      if (!$target.hasClass(ClassName.ITEM_HAS_MENU)) {
        $old.removeClass(ClassName.ITEM_IS_ACTIVE);
        $target.addClass(ClassName.ITEM_IS_ACTIVE);
        $target.closest('.'.concat(ClassName.ITEM).concat('.').concat(ClassName.ITEM_HAS_MENU)).removeClass(ClassName.ITEM_IS_HOVER);
      }

      this.$emit('select.'.concat(MODULE_NAME), {
        elem: $target
      });
    };

    NavMenu.prototype.flexible = function() {
      if (!this.$elem || !this.$elem.length) return;

      var action = arguments.length > 0 ? arguments[0] : 'toggle';
      var $menu = this.$elem.children('.' + ClassName.MENU);

      if (action === 'toggle') {
        $menu.toggleClass(ClassName.IS_SHRINK);
      } else {
        $menu[action ? 'addClass' : 'removeClass'](ClassName.IS_SHRINK);
      }
    };

    NavMenu.prototype.bindEvents = function() {
      if (!this.$elem || !this.$elem.length) return;

      var $menu = this.$elem.children('.'.concat(ClassName.MENU));
      var othis = this;

      $menu.on('click', '.'.concat(ClassName.ITEM).concat(':not(.').concat(ClassName.ITEM_HAS_MENU).concat(')'), function(e) {
        e.preventDefault();
        var $this = $(this);
        var target = $this.data('id');
        othis.select(target);
      });

      $(document).on('mouseenter', '.'.concat(ClassName.MENU, ' .').concat(ClassName.ITEM), function() {
        var $this = $(this);
        var $target = $this.children('.'.concat(ClassName.MENU, '.').concat(ClassName.IS_SUBMENU));
        var $window = $(window);
        var thisTop = $this.offset().top;
        var thisLeft = $this.offset().left;
        var style = {};
        var wrapTop;
        var windowWidth;
        var windowHeight;
        var targetHeight;
        var maxHeight;

        $this.addClass(ClassName.ITEM_IS_HOVER);

        if ($this.hasClass(ClassName.ITEM_HAS_MENU)) {
          wrapTop = $menu.offset().top;
          windowWidth = $window.width();
          windowHeight = $window.height();
          targetHeight = $target.height();
          maxHeight = windowHeight - wrapTop - 5;

          if (targetHeight >= maxHeight) {
            style.maxHeight = maxHeight;
            style.overflowY = 'auto';
          }

          if (thisLeft + $this.width() * 2.5 + 10 >= windowWidth) {
            style.maxWidth = Math.max(0, windowWidth - $target.offset().left - 10);
          }

          if (thisTop + targetHeight > windowHeight) {
            style.top = windowHeight - thisTop - Math.min(targetHeight, maxHeight) - 5;
          }

          $target.css(style);
        } else {
          $this.data('level') === 1 && $menu.hasClass(ClassName.IS_SHRINK) && $this.data('index', layer.tips($this.data('tips'), $this, {
            tips: 2,
            time: 0
          }));
        }
      }).on('mouseleave', '.'.concat(ClassName.MENU, ' .').concat(ClassName.ITEM), function(e) {
        var $this = $(this);
        var $target = $this.children('.'.concat(ClassName.MENU, '.').concat(ClassName.IS_SUBMENU));

        $this.removeClass(ClassName.ITEM_IS_HOVER);

        $this.hasClass(ClassName.ITEM_HAS_MENU) ? $target.css({
          position : '',
          maxWidth : '',
          maxHeight: '',
          overflowY: '',
          top      : ''
        }) : layer.close($this.data('index'));
      });
    };

    exports(MODULE_NAME, NavMenu);
  });
// eslint-disable-next-line no-undef
}(layui, window, document));
